﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.XtraEditors;
using System.Windows.Forms;
using System.ComponentModel;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraEditors.Registrator;
using System.Drawing;
using DevExpress.Utils.Drawing;
using DevExpress.XtraEditors.Drawing;
using DevExpress.XtraEditors.ViewInfo;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Popup;
using DevExpress.LookAndFeel;

namespace ProgNetComponentsDx.Controls.Editors
{
    public class MultilineTextEditPopupForm : BlobBasePopupForm
    {
        private MemoEdit memo;

        protected override Control EmbeddedControl
        {
            get
            {
                return (Control)this.Memo;
            }
        }

        protected virtual MemoEdit Memo
        {
            get
            {
                return this.memo;
            }
        }

        [Browsable(false)]
        public new MultilineTextEdit OwnerEdit
        {
            get
            {
                return base.OwnerEdit as MultilineTextEdit;
            }
        }

        [Category("Appearance")]
        public override object ResultValue
        {
            get
            {
                return this.Memo.EditValue;
            }
        }

        public MultilineTextEditPopupForm(MultilineTextEdit ownerEdit)
            : base(ownerEdit)
        {
            this.memo = new MemoEdit();
            if (this.OwnerEdit.LookAndFeel.ActiveStyle != ActiveLookAndFeelStyle.Skin)
                this.memo.Properties.BorderStyle = BorderStyles.Simple;
            this.memo.Properties.Appearance.Assign(ownerEdit.Properties.AppearanceDropDown);
            //this.memo.scrollHelper.LookAndFeel = this.OwnerEdit.LookAndFeel;
            this.memo.MenuManager = this.OwnerEdit.MenuManager;
            this.memo.Visible = false;
            memo.Properties.AcceptsTab = ownerEdit.Properties.AcceptsTab;
            MemoEdit memoEdit = this.memo;
            MultilineTextEditPopupForm memoExPopupForm = this;

            memoEdit.Modified += new EventHandler(memoEdit_Modified);
            this.Controls.Add((Control)this.memo);
            this.UpdateMemo();
        }

        void memoEdit_Modified(object sender, EventArgs e)
        {

        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && this.Memo != null)
            {
                MemoEdit memoEdit = this.memo;
                MultilineTextEditPopupForm memoExPopupForm = this;
               
                memoEdit.Modified -=new EventHandler(memoEdit_Modified);

                this.memo.Dispose();
                this.memo = (MemoEdit)null;
            }
            base.Dispose(disposing);
        }

        protected virtual void UpdateMemo()
        {
            this.Memo.Properties.BeginUpdate();
            try
            {
                this.Memo.Properties.Appearance.Assign(this.ViewInfo.PaintAppearanceContent);
                this.Memo.Properties.ReadOnly = this.OwnerEdit.Properties.ReadOnly;
                this.Memo.Properties.MaxLength = this.OwnerEdit.Properties.MaxLength;
                //this.Memo.Properties.AcceptsReturn = this.OwnerEdit.Properties.AcceptsReturn;
                //this.Memo.Properties.AcceptsTab = this.OwnerEdit.Properties.AcceptsTab;
                this.Memo.Properties.ScrollBars = this.OwnerEdit.Properties.ScrollBars;
                this.Memo.Properties.WordWrap = this.OwnerEdit.Properties.WordWrap;
                this.Memo.Properties.CharacterCasing = this.OwnerEdit.Properties.CharacterCasing;
            }
            finally
            {
                this.Memo.Properties.EndUpdate();
            }
        }

        public override void ProcessKeyDown(KeyEventArgs e)
        {
            if (e.KeyData == (Keys.Return | Keys.Control))
            {
                e.Handled = true;
                this.OwnerEdit.ClosePopup();
            }
            else
            {
                if (e.KeyCode == Keys.Tab)
                    return;
                base.ProcessKeyDown(e);
            }
        }

        public override void ShowPopupForm()
        {
            this.BeginControlUpdate();
            try
            {
                this.Memo.EditValue = this.OwnerEdit.EditValue;
                this.Memo.IsModified = false;
            }
            finally
            {
                this.EndControlUpdate();
            }
            base.ShowPopupForm();
            this.memo.Update();
            //this.Memo.scrollHelper.UpdateScrollBars();
            this.FocusFormControl((Control)this.Memo);
        }

        protected virtual void OnMemo_Modified(object sender, EventArgs e)
        {
            if (this.IsControlUpdateLocked)
                return;
            this.OkButton.Enabled = true;
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            if (this.Visible)
                this.UpdateMemo();
            base.OnVisibleChanged(e);
        }

        
    }
    
    [ToolboxItem(true)]
    public class MultilineTextEdit : BlobBaseEdit
    {
        [Browsable(false)]
        public override string EditorTypeName { get { return "MultilineTextEdit"; } }

        public MultilineTextEdit()
            : base()
        {
            //memo.Dock = DockStyle.Left;
            //memo.Width = 0;
            //memo.TabStop = false;
            //memo.Properties.AllowFocused = false;
            //this.Controls.Add(memo);
            MaskBox.Multiline = true;
            MaskBox.WordWrap = false;
            MaskBox.ScrollBars = ScrollBars.None;
            //memo.Closed += new ClosedEventHandler(memo_Closed);
        }

        protected override PopupBaseForm CreatePopupForm()
        {
            return new MultilineTextEditPopupForm(this);
        }
        
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Category("Properties")]
        public new RepositoryItemMultilineTextEdit Properties { get { return fProperties as RepositoryItemMultilineTextEdit; } }

        protected override void CreateRepositoryItem()
        {
            fProperties = new RepositoryItemMultilineTextEdit(this);
        }

    }

    [UserRepositoryItem("Register")]
    public class RepositoryItemMultilineTextEdit : RepositoryItemBlobBaseEdit
    {
        private bool _IsMultilineIconLeft;
        #region static
        static RepositoryItemMultilineTextEdit()
        {
            Register();
        }
        public static void Register()
        {
            EditorRegistrationInfo.Default.Editors.Add(
                new EditorClassInfo("MultilineTextEdit",
                                typeof(MultilineTextEdit),
                                typeof(RepositoryItemMultilineTextEdit),
                                typeof(MultilineTextEditViewInfo),
                                new MultilineTextEditPainter(),
                                true,
                                null));
        }
        #endregion

        [DXCategory("Behavior")]
        [Description("Gets or sets a value indicating which scrollbars are displayed within the editor's dropdown window.")]
        public ScrollBars ScrollBars { get; set; }
        
        [DefaultValue(true)]
        [DXCategory("Behavior")]
        [Description("Gets or sets a value specifying whether the text is automatically wrapped at the right margin of the editor's dropdown window.")]
        public bool WordWrap { get; set; }
        
        [Description("Gets or sets tooltip for Multiline icon")]
        public string MultiLineToolTip { get; set; }

        [Description("Gets or sets whether Multiline icon is displayed on left.")]
        public bool IsMultilineIconLeft
        {
            get { return _IsMultilineIconLeft; }
            set
            {
                if (_IsMultilineIconLeft != value)
                {
                    _IsMultilineIconLeft = value;
                    OnPropertiesChanged();
                }
            }
        }

        [DXCategory("Behavior")]
        [Description("Gets or sets a value specifying whether a user can insert tab characters into text.")]
        [DefaultValue(true)]
        public bool AcceptsTab { get; set; }

        private void Initialize()
        {
            fTextEditStyle = TextEditStyles.Standard;
            MultiLineToolTip = "Multiline";
            AcceptsTab = true;
        }
        public RepositoryItemMultilineTextEdit()
            : base()
        {
            Initialize();
        }

        public RepositoryItemMultilineTextEdit(MultilineTextEdit edit)
        {
            SetOwnerEdit(edit);
            Initialize();
        }
        
        public override BaseEdit CreateEditor()
        {
            return new MultilineTextEdit();
        }
        //public override void CreateDefaultButton()
        //{
        //    base.CreateDefaultButton();
        //    if (this.Buttons.Count > 0)
        //        this.Buttons[0].Kind = DevExpress.XtraEditors.Controls.ButtonPredefines.Combo;
        //}
        public override void Assign(RepositoryItem item)
        {
            base.Assign(item);
            RepositoryItemMultilineTextEdit rep = item as RepositoryItemMultilineTextEdit;
            if (rep != null)
            {
                this.ScrollBars = rep.ScrollBars;
                this.WordWrap = rep.WordWrap;
                this.MultiLineToolTip = rep.MultiLineToolTip;
                this.AcceptsTab = rep.AcceptsTab;
                this.IsMultilineIconLeft = rep.IsMultilineIconLeft;
            }
        }

        public override TextEditStyles TextEditStyle
        {
            get
            {
                return this.fTextEditStyle;
            }
            set
            {
                if (this.TextEditStyle == value)
                    return;
                this.fTextEditStyle = value;
                this.OnTextEditStyleChanged();
                this.OnPropertiesChanged();
            }
        }
        public override BaseEditViewInfo CreateViewInfo()
        {
            return new MultilineTextEditViewInfo(this);
        }
        public override BaseEditPainter CreatePainter()
        {
            return new MultilineTextEditPainter();
        }
    }
    
    public class MultilineTextEditPainter : BlobBaseEditPainter
    {
        protected override void DrawContent(ControlGraphicsInfoArgs info)
        {
            MultilineTextEditViewInfo vi = info.ViewInfo as MultilineTextEditViewInfo;
            if (vi != null)
                vi.CalcViewInfo(info.Graphics);
            base.DrawContent(info);
        }
    }

    public class MultilineTextEditViewInfo : BlobBaseEditViewInfo
    {
        public MultilineTextEditViewInfo(RepositoryItemMultilineTextEdit item)
            : base(item)
        {

        }
        private EditorButton btn = new EditorButton(ButtonPredefines.Glyph, "", 17, false, true, false, DevExpress.Utils.HorzAlignment.Center, Properties.Resources.multiline.ResizeImage(17, 17), null);
        public override void CalcViewInfo(Graphics g)
        {
            btn.ToolTip = ((RepositoryItemMultilineTextEdit)this.Item).MultiLineToolTip;
            base.CalcViewInfo(g);
        }
        protected override Rectangle CalcButtons(GraphicsCache cache)
        {
            bool flag = this.Item.TextEditStyle == TextEditStyles.HideTextEditor;

            if (this.DisplayText.Contains('\n'))
            {
                EditorButtonObjectInfoArgs newBtn = this.CreateButtonInfo(btn, 0);
                newBtn.FillBackground = this.FillBackground;
                this.CalcButtonState(newBtn, 0);
                newBtn.Cache = cache;
                bool isLeft = false;
                isLeft = ((RepositoryItemMultilineTextEdit)this.Item).IsMultilineIconLeft;
               
                if (isLeft)
                    this.LeftButtons.Add(newBtn);
                else
                    this.RightButtons.Add(newBtn);
            }
            for (int index = 0; index < this.Item.Buttons.Count; ++index)
            {
                EditorButton button = this.Item.Buttons[index];
                if (button.Visible)
                {
                    EditorButtonObjectInfoArgs buttonInfo = this.CreateButtonInfo(button, index);
                    buttonInfo.FillBackground = this.FillBackground;
                    this.CalcButtonState(buttonInfo, index);
                    buttonInfo.Cache = cache;
                    if (button.IsLeft)
                        this.LeftButtons.Add(buttonInfo);
                    else
                        this.RightButtons.Add(buttonInfo);
                }
            }

            ButtonEditViewInfo.CalcButtonsRectsArgs buttonsRectsArgs = this.CreateCalcButtonsRectsArgs(this.ClientRect);
            buttonsRectsArgs.UseAutoFit = flag;
            buttonsRectsArgs.ViewInfo = this;
            buttonsRectsArgs.Calc();
            this.RightButtons.SetCache((GraphicsCache)null);
            this.LeftButtons.SetCache((GraphicsCache)null);
            return buttonsRectsArgs.ClientRect;

        }

        protected override Size CalcClientSize(Graphics g)
        {
            Size size1 = base.CalcClientSize(g);
            Size size2 = Size.Empty;
            this.GInfo.AddGraphics(g);
            bool flag = this.Item.TextEditStyle == TextEditStyles.HideTextEditor;

            if (this.DisplayText.Contains('\n'))
            {
                EditorButtonObjectInfoArgs buttonInfo = this.CreateButtonInfo(btn, 0);
                buttonInfo.Cache = this.GInfo.Cache;
                Size size3 = this.CalcMinButtonBounds(buttonInfo);
                size2.Height = Math.Max(size2.Height, size3.Height);
                size2.Width += size3.Width;
            }
            try
            {
                for (int index = 0; index < this.Item.Buttons.Count; ++index)
                {
                    EditorButton button = this.Item.Buttons[index];
                    if (button.Visible)
                    {
                        EditorButtonObjectInfoArgs buttonInfo = this.CreateButtonInfo(button, index);
                        buttonInfo.Cache = this.GInfo.Cache;
                        Size size3 = this.CalcMinButtonBounds(buttonInfo);
                        size2.Height = Math.Max(size2.Height, size3.Height);
                        size2.Width += size3.Width;
                    }
                }
            }
            finally
            {
                this.GInfo.ReleaseGraphics();
            }
            size1.Height = Math.Max(size1.Height, size2.Height);
            if (this.IsDrawButtons)
                size1.Width += size2.Width;
            return this.UpdateByGlyphSize(size1);
        }
    }
}
